type Mod = string | {[key: string]: any}
type Mods = Mod | Mod[]

function gen(name: string, mods?: Mods): string {
  if (!mods) {
    return ''
  }

  if (typeof mods === 'string') {
    return ` ${name}--${mods}`
  }

  if (Array.isArray(mods)) {
    return mods.reduce<string>((pre, cur) => pre + gen(name, cur), '')
  }

  return Object.keys(mods).reduce<string>((pre, cur) => pre + (mods[cur] ? gen(name, cur) : ''), '')
}

function createBEM(name: string) {
  return (el?: Mods, mods?: Mods): Mods => {
    if (el && typeof el !== 'string') {
      mods = el
      el = ''
    }

    el = el ? `${name}__${el}` : name
    return `${el}${gen(el, mods)}`
  }
}

type BEM = ReturnType<typeof createBEM>

export function createNamespace(name: string): [BEM] {
  name = `ly-${name}`
  return [createBEM(name)]
}